var vue = new Vue({
    el: '#page_container',
    data: function () {
        return {
            index: {
                name: 'index',
                label: '主页',
                queryForm: { queryString: '', likeChecked: false, loading: false, classType: [1, 3] },
                queryExpandRowKeys: [],
                queryResult: [],
                queryResultSortable: true,
                contextData: NaN,
                showAllContextData: false,
            },
            enums: {
                //元数据类型
                classTypeOptions: [
                    { value: 0, name: '基本', isQuery: false, isFilter: true },
                    { value: 1, name: '实体', isQuery: true, isFilter: true },
                    { value: 2, name: '属性', isQuery: true, isFilter: true },
                    { value: 3, name: '枚举', isQuery: true, isFilter: true },
                    { value: 4, name: '集合', isQuery: false, isFilter: true },
                    { value: 7, name: 'BPSV', isQuery: true, isFilter: false }
                ],
                //事务类型
                transactionTypeOptions: [
                    { value: 0, name: 'Required' },
                    { value: 1, name: 'RequiresNew' },
                    { value: 2, name: 'Supported' },
                    { value: 3, name: 'NotSupported' }
                ],
                //关联种类
                enumAssociationKindOptions: [
                    { value: 0, code: 'ASSOCIATION', name: '关联' },
                    { value: 1, code: 'COMPOSITION', name: '组合' }
                ],
                //关联种类
                queryOperatorOptions: [
                    { value: 0, code: '%like', name: '左包含' },
                    { value: 1, code: 'like', name: '包含' },
                    { value: 2, code: 'like%', name: '右包含' },
                    { value: 3, code: 'equal', name: '等于' }
                ],
                //关联种类
                monacoEditorThemeOptions: [
                    { value: 0, code: 'vs', name: 'vs' },
                    { value: 1, code: 'vs-dark', name: 'vs-dark' },
                    { value: 2, code: 'hc-black', name: 'hc-black' }
                ],
                //值集定义-类型
                ValueSetDefValidateTypeEnum: [
                    { value: 1, code: 'Entity', name: '实体' },
                    { value: 2, code: 'None', name: '无档案' },
                    { value: 3, code: 'ValueSet', name: '自定义' },
                    { value: 4, code: 'EnumType', name: '枚举' }
                ],
                //值集定义-段值类型
                ValueSetDefValueTypeEnum: [
                    { value: 1, code: 'VtInteger', name: '整数' },
                    { value: 2, code: 'VtString', name: '字符串' },
                    { value: 3, code: 'VtDate', name: '日期' },
                    { value: 4, code: 'VtNumber', name: '数字' },
                    { value: 5, code: 'VtBool', name: '布尔' },
                    { value: 6, code: 'VtDateTime', name: '日期时间' }
                ],
            },
            constObj: {
                descFlexSegmentsFullName: 'UFIDA.U9.Base.FlexField.DescFlexField.DescFlexSegments',
            },
            currentTabIndex: 'index',
            monacoEditorTheme: 0,
            tabs: [],
            metedatas: [],
            oqlExpressions: [],
            formulaExpressions: [],
            popover: {
                oqlExpressionActiveAttribute: NaN,
                oqlExpressionActiveReference: NaN,
                oqlExpressionShow: false,
                formulaExpressionActiveAttribute: NaN,
                formulaExpressionActiveReference: NaN,
                formulaExpressionShow: false,
            }
        }
    },
    beforeCreate: function () {
        if (window && window.parent && window.parent.TabPanelManager) {
            let _parentWin = window.parent;
            let url = window.location.href;
            setTimeout(function () {
                _parentWin.TabPanelManager.killThis();
            }, 100);
            _parentWin.window.open(url, '_blank');
        }
    },
    created: function () {
        this.oqlExpressions = oqlExpressions;
        this.formulaExpressions = formulaExpressions;
    },
    mounted: function () {
        require.config({
            paths: { vs: '../../classView/js/monaco-editor-0.46.0/min/vs' },
            'vs/nls': { availableLanguages: { '*': 'zh-cn' } }
        });
        //获取当前上下文
        this.getCurrentContext();
    },
    methods: {
        api() {
            let $this = this;
            return {
                //查询元数据
                queryMetedata(parameter, resolve) {
                    $.post("../classView/QueryMetedata", parameter, resolve);
                },
                //获取Metedata
                getMetedata(keyID, parentFullName, resolve) {
                    let url = "../classView/GetMetedata?keyID=" + encodeURIComponent(keyID) +
                        (parentFullName && parentFullName.length > 0 ?
                            "&parentFullName=" + encodeURIComponent(parentFullName) : "")
                    $.get(url, resolve);
                },
                //获取当前上下文
                getCurrentContext(resolve) {
                    $.post("../classView/GetCurrentContext", resolve);
                },
                //获取代理对象
                getProxyData(parameter, resolve) {
                    $.post("../classView/GetProxyData", parameter, resolve);
                },
                //累计重载代理对象
                totalGetProxyData(parameter, resolve) {
                    $.post("../classView/TotalGetProxyData", parameter, resolve);
                },
                //执行代理请求
                proxyDo(parameter, resolve) {
                    $.post("../classView/ProxyDo", parameter, resolve);
                },
                //Oql转为Sql
                convertOqlToSql(oql, resolve) {
                    $.post("../classView/ConvertOqlToSql", { oql: oql }, resolve);
                },
                //执行Oql
                runOQL(oql, pageParamter, resolve) {
                    $.post("../classView/RunOQL", { oql: oql, pageParamter: JSON.stringify(pageParamter) }, resolve);
                },
                //开启事务调试
                setupTransactionDebug(resolve) {
                    $.get("../classView/SetupTransactionDebug", {}, resolve);
                },
                //开启拦截调试
                setupProxyDoDebug(resolve) {
                    $.get("../classView/SetupProxyDoDebug", {}, resolve);
                },
            }
        },
        //#region 左侧通用按钮
        //回主页
        goHome() {
            this.currentTabIndex = this.index.name;
        },
        //回到上一页
        goBack(tab) {
            if (tab && tab.preTabIndex) {
                this.currentTabIndex = tab.preTabIndex;
            }
        },
        //刷新
        onRefresh(tab) {
            let $this = this;
            if (!tab.metedata) return;
            let classType = tab.metedata.ClassType;
            let keyID = tab.name;
            this.addMetedataTab(classType, keyID, true);
        },
        //#endregion
        //#region monaco.editor
        //获取编辑器配置
        getEditorConfig(language, value) {
            return {
                language: language,
                value: value,
                contextmenu: true,
                acceptSuggestionOnCommitCharacter: true,
                acceptSuggestionOnEnter: 'on',
                accessibilityPageSize: 10,
                accessibilitySupport: 'on',
                autoClosingBrackets: 'always',
                autoClosingDelete: 'always',
                autoClosingOvertype: 'always',
                autoClosingQuotes: 'always',
                autoIndent: 'None',
                automaticLayout: true,
                codeLens: false,
                codeLensFontFamily: '',
                codeLensFontSize: 12,
                colorDecorators: false,
                comments: {
                    ignoreEmptyLines: true,
                    insertSpace: true
                },
                columnSelection: false,
                autoSurround: 'never',
                copyWithSyntaxHighlighting: true,
                cursorBlinking: 'Solid',
                cursorSmoothCaretAnimation: true,
                cursorStyle: 'UnderlineThin',
                cursorSurroundingLines: 0,
                cursorSurroundingLinesStyle: 'all',
                cursorWidth: 2,
                minimap: {
                    enabled: false
                },
                folding: true,
                links: true,
                overviewRulerBorder: false,
                renderLineHighlight: 'gutter',
                roundedSelection: false,
                scrollBeyondLastLine: false,
                readOnly: false,
                theme: 'vs',
                fontSize: "12px",
                lineNumbers: "on",
            };
        },
        //格式化
        formatEditorValue(editor) {
            if (!editor) return;
            let language = editor._configuration._rawOptions.language;
            if (language === "json") {
                editor.trigger('anyString', 'editor.action.formatDocument')
                editor.setValue(editor.getValue())
            }
            if (language === "sql") {
                require(['sqlFormatter'], function (sqlFormatter) {
                    if (!sqlFormatter) return;
                    let sql = editor.getValue();
                    let config = {
                        language: "tsql",
                        expressionWidth: 100,
                        keywordCase: editor.isOQL ? "lower" : "upper",
                        functionCase: editor.isOQL ? "preserve" : "upper",
                    };
                    editor.setValue(sqlFormatter.format(sql, config));
                });
            }
        },
        //全部展开
        editorExpandAll(editor) {
            if (!editor) return;
            editor.trigger('unfold', 'editor.unfoldAll');
        },
        //全部收缩
        editorCollapseAll(editor) {
            if (!editor) return;
            editor.trigger('fold', 'editor.foldAll');
        },
        //当编辑器样式变化
        onMonacoEditorThemeChange() {
            if (typeof monaco === "undefined") return;
            let themeOption = this.enums.monacoEditorThemeOptions.find(
                (option) => {
                    return option.value == this.monacoEditorTheme;
                });
            if (themeOption)
                monaco.editor.setTheme(themeOption.code);
        },
        //#endregion
        //#region 元数据
        //获取Metedata
        getMetedata(keyID, parentFullName, resolve) {
            let metedatas = this.metedatas;
            let metedata = metedatas.find((item) => item.Key && item.Key.ID == keyID +
                (parentFullName && parentFullName.length > 0 ? "_" + parentFullName : ''));
            if (metedata && resolve) {
                resolve(metedata);
                return;
            }
            let $this = this;
            this.api().getMetedata(keyID, parentFullName, function (res) {
                //console.log('res', res)
                if (res.code === 0) {
                    //console.log('metedata name:', res.data.Name + '/' + res.data.DisplayName)
                    console.log('metedata', JSON.stringify(res.data))
                    metedata = res.data;
                    if (parentFullName && parentFullName.length > 0)
                        metedata.Key.ID = metedata.Key.ID + "_" + parentFullName;
                    $this.metedatas.push(metedata);
                    if (resolve) resolve(metedata);
                }
                else {
                    $this.$notify.error({
                        title: '错误',
                        message: res && res.msg ? res.msg : '未知',
                        duration: 1000
                    });
                }
            });
        },
        //获取克隆后的Metedata
        getCloneMetedata(keyID, parentFullName, resolve) {
            this.getMetedata(keyID, parentFullName, function (metedata) {
                let cloneMetedata = $.extend(true, {}, metedata)
                if (resolve) resolve(cloneMetedata);
            });
        },
        //补齐Entity元数据
        patchEntityMetedata(metedata, parentAttribute, parentAssociation) {
            metedata.ID = Math.uuid();
            //补齐Entity元数据属性
            this.patchEntityMetedataAttributes(metedata, parentAttribute);
            //补齐Entity元数据关联
            this.patchEntityMetedataAssociations(metedata, parentAssociation);
        },
        //补齐Entity元数据属性
        patchEntityMetedataAttributes(metedata, parentAttribute) {
            let $this = this;
            metedata.Attributes.forEach((attribute, index) => {
                attribute.attributeID = Math.uuid();
                attribute.metedata = metedata;
                attribute.parentAttribute = parentAttribute;
                if (parentAttribute)
                    metedata.tab = parentAttribute.metedata.tab;
                attribute.hasChildren = attribute.DataTypeFlag == 1 || attribute.DataTypeFlag === 2 || attribute.DataTypeFlag === 4;
                attribute.children = [];
                //表达式
                if (metedata.ClassType === 2 && parentAttribute) { //属性
                    attribute.expression = parentAttribute.metedata.Name + '.' + parentAttribute.Name.concat('.', attribute.Key.Name);
                    attribute.expressionDisplayName = parentAttribute.metedata.DisplayName + '.' + parentAttribute.DisplayName.concat('.', attribute.DisplayName);
                } else {
                    attribute.expression = metedata.Key.Name.concat('.', attribute.Key.Name);
                    attribute.expressionDisplayName = metedata.DisplayName.concat('.', attribute.DisplayName);
                }

                if (parentAttribute) {
                    //完整表达式
                    attribute.fullExpression = parentAttribute.fullExpression.concat('.', attribute.Key.Name);
                    attribute.fullExpressionDisplayName = parentAttribute.fullExpressionDisplayName.concat('.',
                        attribute.DescFlexFieldDef && attribute.DescFlexFieldDef.Name ?
                            attribute.DescFlexFieldDef.Name : attribute.DisplayName);
                    attribute.level = parentAttribute.level + 1;
                } else {
                    //完整表达式
                    attribute.fullExpression = attribute.expression;
                    attribute.fullExpressionDisplayName = attribute.expressionDisplayName;
                    attribute.level = 1;
                }
                //关联(继承实体关联会不存在)
                if (attribute.DataTypeFlag === 1 || attribute.DataTypeFlag === 4) {
                    let association = metedata.Associations.find((asso) => {
                        return asso.ParentMemberKey && asso.ParentMemberKey.ID == attribute.Key.ID
                    });
                    if (association) {
                        attribute.DataTypeKey = association.ChildEntityKey;
                        attribute.DataTypeKind = association.Kind;
                        attribute.association = association;
                    }
                }
                attribute.oqlExpressions = [];
                attribute.formulaExpressions = [];
                //属性
                //if(attribute.DataTypeFlag===2)
                //    $this.loadAttributeChildAttributes(attribute);
            });
        },
        //补齐Entity元数据关联
        patchEntityMetedataAssociations(metedata, parentAssociation) {
            metedata.Associations.forEach((association, index) => {
                association.associationID = Math.uuid();
                association.metedata = metedata;
                association.parentAssociation = parentAssociation;
                if (parentAssociation)
                    metedata.tab = parentAssociation.metedata.tab;
                association.children = [];
                //表达式
                association.expression = ''.concat(association.ParentEntityKey.Name, '.', association.ParentMemberKey.Name);
                if (parentAssociation) {
                    //完整表达式
                    association.fullExpression = parentAssociation.fullExpression.concat('.', association.ParentMemberKey.Name);
                    association.level = parentAssociation.level + 1;
                } else {
                    //完整表达式
                    association.fullExpression = association.expression;
                    association.level = 1;
                }
            });
        },
        //加载属性的子属性
        loadAttributeChildAttributes(attribute, treeNode, resolve) {
            if (attribute.DataTypeFlag !== 1 && attribute.DataTypeFlag !== 2 && attribute.DataTypeFlag !== 4) return;
            //实体或属性
            let keyID = attribute.DataTypeKey.ID;
            let $this = this;
            let parentFullName = attribute.DataTypeKey.FullName === this.constObj.descFlexSegmentsFullName ?
                attribute.metedata.Key.FullName : NaN;
            this.getCloneMetedata(keyID, parentFullName, function (metedata) {
                //补齐Entity元数据属性
                $this.patchEntityMetedata(metedata, attribute);
                attribute.children = metedata.Attributes;
                if (resolve)
                    resolve(metedata.Attributes);
            });
        },
        //加载子实体关联
        loadChildrenAssociations(association, treeNode, resolve) {
            let keyID = association.ChildEntityKey.ID;
            let $this = this;
            this.getCloneMetedata(keyID, NaN, function (metedata) {
                //补齐Entity元数据关联
                $this.patchEntityMetedata(metedata, NaN, association);
                let associations = $this.filterAssociationsByKind(metedata, 1);
                association.children = associations;
                resolve(associations);
            })
        },
        //获取扩展字段
        getDescFlexSegmentsAttribute(metedata) {
            if (!metedata || !metedata.Attributes) return NaN;
            let attr = metedata.Attributes.find(
                (attribute) => attribute.DataTypeKey && attribute.DataTypeKey.FullName == this.constObj.descFlexSegmentsFullName);
            return attr;
        },
        //复制所有的属性
        copyAllAttributes(metedata) {
            if (metedata && metedata.Attributes && metedata.Attributes.length > 0) {
                let content = '';
                metedata.Attributes.forEach((attribute, index) => {
                    if (index > 0) {
                        content += '\r';
                    }
                    content = content + attribute.Name + '\t' + attribute.DisplayName;
                });
                this.copyToClipboard(content);
            }
        },
        //#endregion
        //#region Tabs
        //Tabs编辑事件
        handleTabsEdit(targetName, action) {
            if (action === 'remove') {
                if (targetName === this.index.name) return;
                let tabs = this.tabs;
                let activeName = this.currentTabIndex;
                if (activeName === targetName) {
                    tabs.forEach((tab, index) => {
                        if (tab.name === targetName) {
                            activeName = tab.preTabIndex;
                        }
                    });
                }
                this.currentTabIndex = activeName;
                this.tabs = this.tabs.filter(tab => tab.name !== targetName);
                if (!this.tabs || this.tabs.length === 0) {
                    this.currentTabIndex = this.index.name;
                }
            }
        },
        //新增元数据Tab
        addMetedataTab(classType, keyID, refresh) {
            if (classType === 1) this.addEntityTab(keyID, refresh);
            if (classType === 2) this.addPropertyTypeTab(keyID, refresh);
            if (classType === 3) this.addEnumTab(keyID, refresh);
            if (classType === 7) this.addBPSVTab(keyID, refresh);
        },
        //新增实体元数据Tab
        addEntityTab(keyID, refresh) {
            let $this = this;
            this.addBaseMetedataTab(keyID, refresh, function (tab) {
                tab.type = "entity";
                tab.expandrowkeys = [];
                tab.activeNames = ["tabMainAttributes"];
                tab.filterParameter = {
                    filterString: '',
                    confirmFilterString: '',
                    filterOperatorType: 0,
                    isOnlyFilterTopLevel: true,
                    filterClassType: [-1]
                };
                tab.mainTableLoading = false;
                tab.currentAttribute = NaN;
                //补齐Entity元数据
                $this.patchEntityMetedata(tab.metedata);
            });
        },
        //新增属性元数据Tab
        addPropertyTypeTab(keyID, refresh) {
            let $this = this;
            this.addBaseMetedataTab(keyID, refresh, function (tab) {
                tab.type = 'propertyType';
                tab.expandrowkeys = [];
                tab.activeNames = ["tabMainAttributes"];
                tab.filterParameter = {
                    filterString: '',
                    confirmFilterString: '',
                    filterOperatorType: 0,
                    isOnlyFilterTopLevel: true,
                    filterClassType: [-1]
                };
                tab.mainTableLoading = false;
                tab.currentAttribute = NaN;
                //补齐Entity元数据
                $this.patchEntityMetedata(tab.metedata);
            });
        },
        //新增枚举元数据Tab
        addEnumTab(keyID, refresh) {
            let $this = this;
            this.addBaseMetedataTab(keyID, refresh, function (tab) {
                tab.type = 'enum';
                tab.activeNames = ["tabMainBase", "tabMainAttributes"];
            });
        },
        //新增BPSV元数据Tab
        addBPSVTab(keyID, refresh, afterInitResolve) {
            let $this = this;
            if (!afterInitResolve)
                afterInitResolve = function (tab) {
                    $this.initBPSVEditor(tab);
                };
            this.addBaseMetedataTab(keyID, refresh, function (tab) {
                tab.type = 'bpsv';
                tab.expandrowkeys = [];
                tab.activeNames = ["bpsvTabMainTest"];
                tab.currentBPSVTabIndex = 'bpsvTabMainTestRequestTab';
                tab.proxyParameter = {
                    proxyFullName: tab.metedata.ProxyFullName,
                    proxyAssemblyName: tab.metedata.ProxyAssemblyName,
                    transferRequestDataByMember: false,
                    requestDataAutoExpandLevel: 2
                };
                tab.proxyAction = {
                    loadProxyDataLoading: false,
                    totalLoadProxyDataLoading: false,
                    proxyDoLoading: false,
                };
                tab.transactionDebug = {
                    webSocket: NaN,
                    isSetupGlobal: false,
                    isSetupProxy: false,
                    logData: []
                };
                tab.proxyDoDebug = {
                    webSocket: NaN,
                    proxyDoDebugLoading: false,
                };
                tab.openBPSVFileName = '';
            }, afterInitResolve);
        },
        //新增元数据Tab
        addBaseMetedataTab(keyID, refresh, resolve, afterInitResolve) {
            if (this.currentTabIndex == keyID && !refresh) return;
            let tab = this.tabs.find((item) => item.name == keyID);
            if (tab && !refresh) {
                tab.preTabIndex = this.currentTabIndex;
                this.currentTabIndex = tab.name;
                if (afterInitResolve) afterInitResolve(tab);
                return;
            }
            let $this = this;
            if (refresh && tab)
                tab.isRefreshLoading = true;
            this.getCloneMetedata(keyID, NaN, function (metedata) {
                if (!tab)
                    tab = {
                        preTabIndex: $this.currentTabIndex,
                    };
                tab.name = metedata.Key.ID;
                tab.title = metedata.DisplayName;
                tab.metedata = metedata;
                metedata.tab = tab;
                if (resolve) resolve(tab);
                if (!refresh) {
                    $this.tabs.push(tab);
                    $this.currentTabIndex = metedata.Key.ID;
                    if (afterInitResolve) {
                        $this.$nextTick(() => {
                            afterInitResolve(tab);
                        })
                    }
                }
                tab.isRefreshLoading = false;
            })
        },
        //新增OQLTab
        addOQLTab(srcTab, key, title, oql) {
            let tabType = 'oql';
            let keyID = key ? key + '-' + tabType :
                (srcTab ? (tabType + '-' + srcTab.name) : (tabType + '-' + Math.uuid()));
            title = title ? 'OQL:' + title : (srcTab ? 'OQL:' + srcTab.title : 'OQL');
            if (this.currentTabIndex === keyID) return;
            let tab = this.tabs.find((item) => item.name && item.name == keyID);
            if (tab) {
                tab.preTabIndex = this.currentTabIndex;
                this.currentTabIndex = tab.name;
                return;
            }
            let $this = this;
            tab = {
                name: keyID,
                type: tabType,
                title: title,
                srcTab: srcTab,
                preTabIndex: $this.currentTabIndex,
                currentOQLTabIndex: 'oqlTabMainOQLTab',
                activeNames: ["oqlTabMainOQL"],
                oqlAction: {
                    convertOqlToSqlLoading: false,
                    runOqlLoading: false,
                },
                runOQLResult: {
                    pageParamter: {
                        pageIndex: 0,
                        pageSize: 20,
                        totalCount: 0,
                        totalPage: 0
                    },
                    queryData: [],
                },
                resultPageSizes: [20, 50, 100, 200, 500, 1000],
                resultFixedColumns: [],
                oqlParameter: {
                    expandEntityTable: false, //扩开表
                    createTempTableWhenCreateSQL: false, //生成SQL时，生成临时表
                    useBusinessKeyForParams: false,//实体主键作为过滤条件
                    useEngcolumnAliasName: false,//列名采用英文
                    sortFieldByRowIndex: false,//按行顺序排列字段
                },
            };
            $this.tabs.push(tab);
            $this.currentTabIndex = keyID;
            $this.$nextTick(() => {
                if (!oql) {
                    if (srcTab && srcTab.type === 'entity')
                        oql = $this.createOQLFromEntityTab(srcTab, tab.oqlParameter);
                    if (srcTab && srcTab.type === 'enum')
                        oql = $this.createOQLFromEnumTab(srcTab);
                }
                $this.initOQLEditor(tab, oql);
            })
        },
        //添加自定义值集OQL
        addValueSetOQLTab(valueSetDef) {
            let oql = ""
                .concat("select\r\n")
                .concat("  DefineValue.Code as 编码,\r\n")
                .concat("  DefineValue.Name as 名称,\r\n")
                .concat("  DefineValue.Effective.IsEffective as 生效,\r\n")
                .concat("  DefineValue.Effective.EffectiveDate as 生效日期,\r\n")
                .concat("  DefineValue.Effective.DisableDate as 失效日期,\r\n")
                .concat("  ValueSetDef.Code as 值集定义编码,\r\n")
                .concat("  ValueSetDef.Name as 值集定义名称\r\n")
                .concat("from\r\n")
                .concat("  UFIDA::U9::Base::FlexField::ValueSet::DefineValue DefineValue\r\n")
                .concat("  inner join UFIDA::U9::Base::FlexField::ValueSet::ValueSetDef ValueSetDef on DefineValue.ValueSetDef = ValueSetDef.ID\r\n")
                .concat("where\r\n")
                .concat("  ValueSetDef.Code = '" + valueSetDef.Code + "'\r\n")
                .concat("order by\r\n")
                .concat("  DefineValue.Code");
            this.addOQLTab(NaN, "ValueSetDef-" + valueSetDef.Code, "值集-" + valueSetDef.Name, oql);
        },
        //通过实体枚举生成OQL
        createOQLFromEnumTab(tab) {
            if (!tab) return;
            let metedata = tab.metedata;
            return ""
                .concat("select\r\n")
                .concat("  ExtEnumValue.Code as 枚举编码,\r\n")
                .concat("  ExtEnumValue.Name as 枚举名称,\r\n")
                .concat("  ExtEnumValue.EValue as 枚举值,\r\n")
                .concat("  ExtEnumValue.IsSystem as 是否系统预制,\r\n")
                .concat("  ExtEnumType.Code as 枚举类型编码,\r\n")
                .concat("  ExtEnumType.Name as 枚举类型名称\r\n")
                .concat("from\r\n")
                .concat("  UFIDA::UBF::MD::Business::ExtEnumValue ExtEnumValue\r\n")
                .concat("  inner join UFIDA::UBF::MD::Business::ExtEnumType ExtEnumType on ExtEnumValue.ExtEnumType = ExtEnumType.ID\r\n")
                .concat("where\r\n")
                .concat("  ExtEnumType.Code = '" + metedata.Key.FullName + "'\r\n")
                .concat("order by\r\n")
                .concat("  ExtEnumValue.EValue");
        },
        //获取当前Tab
        getCurrentTab(pageSize) {
            let $this = this;
            return $this.tabs.find((item) => item.name == $this.currentTabIndex);
        },
        //#endregion
        //#region 首页
        //查询元数据
        queryMetedata() {
            let parameter = {
                "classType": this.index.queryForm.classType.join(","),
                "queryString": this.index.queryForm.queryString,
                "like": this.index.queryForm.likeChecked
            };
            //console.log('parameter', parameter);
            this.index.queryForm.loading = true;
            let $this = this;
            this.api().queryMetedata(parameter, function (res) {
                //console.log("查询结果", res);
                $this.index.queryForm.loading = false;
                if (res.code === 0) {
                    $this.index.queryExpandRowKeys = [];
                    $this.index.queryResult = res.data.map((item, index) => {
                        item.metedata = {};
                        item.loadMetedata = false;
                        item.activeNames = [];
                        return item;
                    });
                } else {
                    $this.$notify.error({
                        title: '错误',
                        message: res && res.msg ? res.msg : '未知',
                        duration: 1000
                    });
                }
            });
        },
        //聚焦元数据
        focusMetedata(classType, queryString) {
            let $this = this;
            this.index.queryForm.loading = true;
            let parameter = {
                "classType": classType,
                "queryString": queryString,
                "focus": true
            };
            this.api().queryMetedata(parameter, function (res) {
                $this.index.queryForm.loading = false;
                if (res.code === 0) {
                    $this.index.queryExpandRowKeys = [];
                    $this.index.queryResult = res.data.map((item, index) => {
                        item.metedata = {};
                        item.loadMetedata = false;
                        return item;
                    });
                } else {
                    $this.$notify.error({
                        title: '错误',
                        message: res && res.msg ? res.msg : '未知',
                        duration: 1000
                    });
                }
            });
        },
        //首页查询结果展开变化
        indexQueryResultExpandChange(row, expandedRows) {
            if (!row.loadMetedata) {
                let keyID = row.ID;
                var $this = this;
                this.getCloneMetedata(keyID, NaN, function (metedata) {
                    metedata.expandrowkeys = [];
                    metedata.isAutoExpandLoading = false;
                    $this.patchEntityMetedata(metedata);
                    $this.$set(row, 'metedata', metedata);
                    $this.$set(row, 'loadMetedata', true);
                });
            }
        },
        //首页查询结果行双击事件
        onIndexQueryResultDblClick(row, column, event) {
            let $this = this;
            let rowRef = $this.$refs[row.ID];
            if (!rowRef) return;
            const expandIcon = rowRef.parentNode.parentNode.parentNode.querySelector(".el-table__expand-icon");
            if (expandIcon) expandIcon.click();
        },
        //是否存在种类关联
        isExistAssociationsByKind(metedata, kind) {
            if (!metedata || !metedata.Associations) return false;
            return metedata.Associations.find((association) => association.Kind === kind);
        },
        //按种类过滤关联
        filterAssociationsByKind(metedata, kind) {
            if (!metedata || !metedata.Associations) return [];
            return kind ? metedata.Associations.filter((association) => association.Kind === kind) : metedata.Associations;
        },
        //自动展开
        autoExpandEntityAssociationTable(metedata) {
            let tableRef = this.$refs[metedata.ID + '_TableRef'];
            if (!tableRef) return;
            let collapseRef = this.$refs[metedata.ID + '_ChildEntityCollapseRef'];
            if (!tableRef || !collapseRef) return;
            if (!collapseRef.activeNames) collapseRef.activeNames = [];
            if (collapseRef.activeNames.indexOf('childEntity') < 0) collapseRef.activeNames.push('childEntity');
            let $this = this;
            metedata.isAutoExpandLoading = true;
            let associations = this.filterAssociationsByKind(metedata, 1);
            let needExpandAssociations = [];
            associations.forEach((association) => {
                if (association.ChildEntityHasChildren)
                    this.loadChildEntityAssociation(association, needExpandAssociations);
            });
            let callback = function () {
                //console.log("needExpandAssociations", needExpandAssociations);
                if (needExpandAssociations.filter(needExpandAssociation => needExpandAssociation.loading == true).length > 0) {
                    setTimeout(callback, 50);
                } else {
                    console.log("全部完成");
                    associations.forEach((association) => {
                        if (association.ChildEntityHasChildren)
                            $this.expandChildEntityAssociation(association);
                    });
                    metedata.isAutoExpandLoading = false;
                }
            };
            callback.call(this);
        },
        //自动收缩
        autoCollapseEntityAssociationTable(metedata) {
            let $this = this;
            let associations = this.filterAssociationsByKind(metedata, 1);
            associations.forEach((association) => {
                if (association.ChildEntityHasChildren)
                    $this.collapseChildEntityAssociation(association);
            });
        },
        //收缩子实体关联
        collapseChildEntityAssociation(association) {
            let $this = this;
            let rowRef = $this.$refs[association.associationID];
            if (!rowRef) return;
            const list = rowRef.parentNode.querySelectorAll(".el-table__expand-icon");
            if (list.length > 0 && list[0].className.includes("el-table__expand-icon--expanded"))
                list[0].click();
            $this.$nextTick(() => {
                if (association.children && association.children.length > 0) {
                    association.children.forEach((childAssociation) => {
                        if (childAssociation.ChildEntityHasChildren)
                            $this.collapseChildEntityAssociation(childAssociation);
                    });
                }
            });
        },
        //加载子实体关联
        loadChildEntityAssociation(association, needExpandAssociations) {
            let $this = this;
            if (association.children && association.children.length > 0) {
                association.children.forEach((childAssociation) => {
                    if (childAssociation.ChildEntityHasChildren)
                        $this.loadChildEntityAssociation(childAssociation, needExpandAssociations);
                });
            }
            else {
                //实体或属性
                let keyID = association.ChildEntityKey.ID;
                let needExpandAssociation = { id: association.associationID, name: association.Name, loading: true };
                needExpandAssociations.push(needExpandAssociation);
                this.getCloneMetedata(keyID, NaN, function (metedata) {
                    let currentMetedata = metedata;
                    //补齐Entity元数据关联
                    $this.patchEntityMetedata(currentMetedata, NaN, association);
                    association.children = $this.filterAssociationsByKind(currentMetedata, 1);
                    association.children.forEach((childAssociation) => {
                        if (childAssociation.ChildEntityHasChildren)
                            $this.loadChildEntityAssociation(childAssociation, needExpandAssociations);
                    });
                    needExpandAssociation.loading = false;
                })
            }
        },
        //展开子实体关联
        expandChildEntityAssociation(association) {
            let $this = this;
            let rowRef = $this.$refs[association.associationID];
            if (!rowRef) return;
            const list = rowRef.parentNode.querySelectorAll(".el-table__expand-icon");
            if (list.length > 0 && !list[0].className.includes("el-table__expand-icon--expanded"))
                list[0].click();
            $this.$nextTick(() => {
                if (association.children && association.children.length > 0) {
                    association.children.forEach((childAssociation) => {
                        if (childAssociation.ChildEntityHasChildren)
                            $this.expandChildEntityAssociation(childAssociation);
                    });
                }
            });
        },
        //获取表格行样式名称
        getAssociationTableRowClassName({ row, rowIndex }) {
            row.rowIndex = rowIndex;
            return '';
        },
        //打开代理测试文件
        onBPSVTestOpenFile(file, fileList) {
            if (!file) return;
            let $this = this;
            let reader = new FileReader();
            reader.readAsText(file.raw, 'UTF-8')
            //读取文件完毕执行此函数
            reader.onload = async function (evt) {
                let jsonData;
                let bpsvFullName;
                try {
                    jsonData = JSON.parse(evt.target.result)
                    if (!jsonData.proxy || jsonData.proxy.length === 0)
                        throw "error";
                    let proxyFullName = jsonData.proxy.split(",")[0];
                    if (!proxyFullName || proxyFullName.length === 0)
                        throw "error";
                    let arr = proxyFullName.split(".");
                    arr[arr.length - 1] = arr[arr.length - 1].slice(0, -5);
                    arr.splice(arr.length - 2, 1);
                    bpsvFullName = arr.join(".");
                } catch (err) {
                    $this.$notify.error({
                        title: '错误',
                        message: '解析文件失败',
                        duration: 1000
                    });
                }
                if (!jsonData) return;
                let parameter = {
                    "classType": 7,
                    "queryString": bpsvFullName,
                    "focus": true
                };
                $this.api().queryMetedata(parameter, function (res) {
                    if (res.code === 0) {
                        if (!res.data || res.data.length === 0) {
                            $this.$notify.error({
                                title: '错误',
                                message: "未找到对应的服务",
                                duration: 1000
                            });
                        }
                        else {
                            $this.addBPSVTab(res.data[0].ID, false, function (tab) {
                                if (tab.editor) {
                                    $this.$confirm('是否重新加载代理数据?', '提示', {
                                        confirmButtonText: '加载',
                                        cancelButtonText: '取消',
                                        type: 'info'
                                    }).then(() => {
                                        tab.openBPSVFileName = file.name;
                                        $this.setJsonEditorValue(tab.editor, JSON.stringify(jsonData.data));
                                    }).catch(() => {
                                        console.log("取消");
                                    });
                                }
                                else {
                                    tab.openBPSVFileName = file.name;
                                    $this.initBPSVEditor(tab, JSON.stringify(jsonData.data));
                                }
                            });
                        }
                    } else {
                        $this.$notify.error({
                            title: '错误',
                            message: res && res.msg ? res.msg : '未知',
                            duration: 1000
                        });
                    }
                });
            }
        },
        //当上下文信息展示
        getCurrentContext(resolve) {
            let $this = this;
            this.api().getCurrentContext(function (res) {
                if (res.code === 0) {
                    $this.index.contextData = res.data;
                    if (resolve) resolve(res.data);
                } else {
                    $this.index.contextData = NaN;
                }
            })
        },
        //#endregion
        //#region 实体页
        //按显示名称排序
        sortDisplayName(a, b) {
            return this.sortStringMethod(a.DisplayName, b.DisplayName);
        },
        //按分组排序
        sortGroupName(a, b) {
            return this.sortStringMethod(a.GroupName, b.GroupName);
        },
        //获取分组数组
        getGroupNameOptions(metedata) {
            let groupNames = [];
            let options = [];
            if (!metedata || !metedata.Attributes || metedata.Attributes.length === 0) return options;
            metedata.Attributes.forEach((attribute, index) => {
                if (groupNames.indexOf(attribute.GroupName) < 0) {
                    groupNames.push(attribute.GroupName);
                }
            });
            groupNames.sort(this.sortStringMethod);
            groupNames.forEach((groupName, index) => {
                options.push({ text: groupName, value: groupName });
            });
            return options;
        },
        //分组过滤
        filterGroupNameHandler(value, row, column) {
            const property = column['property'];
            return row[property] === value;
        },
        //关闭Tab的弹窗
        closeTabPopover(tab, popoverName) {
            let popovers = this.$refs[tab.name + popoverName];
            if (!popovers || !popovers.length || popovers.length === 0) return;
            let popover = popovers[0];
            popover.doClose();
        },
        //获取属性的数量
        getTabAttributesCount(tab) {
            let count = 0;
            let metedata = tab.metedata;
            count += metedata.Attributes.length;
            let $this = this;
            metedata.Attributes.forEach((attribute, index) => {
                count += $this.getAttributChildAttributesCount(attribute);
            });
            return count;
        },
        //获取属性的子属性数量
        getAttributChildAttributesCount(attribute) {
            if (!attribute || !attribute.children) return 0;
            let count = 0;
            count += attribute.children.length;
            let $this = this;
            attribute.children.forEach((attribute, index) => {
                count += $this.getAttributChildAttributesCount(attribute);
            });
            return count;
        },
        //过滤属性确认
        filterAttributesConfirm(tab) {
            tab.filterParameter.confirmFilterString = tab.filterParameter.filterString;
        },
        //当过滤类型变化
        onfilterClassTypeChange(tab) {
            let filterClassType = tab.filterParameter.filterClassType;
            if (!filterClassType || filterClassType.length === 0) tab.filterParameter.filterClassType = [-1];
            if (filterClassType[filterClassType.length - 1] === -1) {
                tab.filterParameter.filterClassType = [-1];
            }
            else {
                let index = filterClassType.indexOf(-1);
                if (index >= 0) {
                    tab.filterParameter.filterClassType.splice(index, 1);
                }
            }
        },
        //获取表格行样式名称
        getTableRowClassName({ row, rowIndex }) {
            row.rowIndex = rowIndex;
            let metedata = row.metedata;
            let tab = metedata.tab;
            let filterString = tab.filterParameter.confirmFilterString;
            let filterClassType = tab.filterParameter.filterClassType;
            if ((!filterString || filterString.length === 0) && filterClassType.indexOf(-1) >= 0) return '';
            filterString = filterString ? filterString.toLowerCase() : '';
            let attribute = row;
            let filterOperatorType = tab.filterParameter.filterOperatorType;
            //只过滤顶层
            let isOnlyFilterTopLevel = tab.filterParameter.isOnlyFilterTopLevel;
            if (isOnlyFilterTopLevel)
                return this.isTableRowAndParentTableRowMatch(attribute, filterString, filterOperatorType, filterClassType) ? '' : "tablerow-hidden";
            let match = this.isTableRowMatch(attribute, filterString, filterOperatorType, filterClassType);
            return (match || this.hasChildEntityTreeData(attribute.children, filterString, filterOperatorType, filterClassType)) ? "" : "tablerow-hidden";
        },
        //当属性OQL表达式点击时
        onAttributeOQLExpressionClick(attribute) {
            if (this.popover.oqlExpressionActiveAttribute == attribute && this.$refs.oqlExpressionPopover.showPopper) return;
            let attrRefs = this.$refs[attribute.attributeID + '_AttributeOQLExpression'];
            if (!attrRefs || !attrRefs.length || attrRefs.length === 0) return;
            let attrRef = attrRefs[0];
            this.popover.oqlExpressionShow = false;
            this.popover.oqlExpressionActiveAttribute = attribute;
            this.popover.oqlExpressionActiveReference = attrRef.$el;
            let $this = this;
            this.$nextTick(() => {
                $this.popover.oqlExpressionShow = true;
                $this.$nextTick(() => {
                    $this.$refs.oqlExpressionPopover.doShow();
                    if (attribute.oqlExpressions && attribute.oqlExpressions.length > 0) {
                        attribute.oqlExpressions.forEach((oqlExpression, index) => {
                            $this.$refs.oqlExpressionTable.toggleRowSelection(oqlExpression, true);
                        });
                    }
                })
            })
        },
        //自动展开
        autoExpandEntityTable(tab, attribute) {
            if (!tab) return;
            let metedata = tab.metedata;
            let $this = this;
            let needExpandAttributes = [];
            tab.mainTableLoading = true;
            if (attribute) {
                if (attribute.DataTypeKind === 1)
                    attribute.isLoading = true;
                this.loadChildEntityAttribute(attribute, needExpandAttributes);
            } else {
                metedata.Attributes.forEach((childAttribute) => {
                    if (childAttribute.DataTypeKind === 1)
                        childAttribute.isLoading = true;
                    this.loadChildEntityAttribute(childAttribute, needExpandAttributes);
                });
            }
            let callback = function () {
                console.log("needExpandAttributes", needExpandAttributes);
                if (needExpandAttributes.filter(needExpandAttribute => needExpandAttribute.loading == true).length > 0) {
                    setTimeout(callback, 50);
                } else {
                    console.log("全部完成");
                    if (attribute) {
                        $this.expandChildEntityAttribute(attribute);
                        if (attribute.DataTypeKind === 1)
                            attribute.isLoading = false;
                    }
                    else {
                        metedata.Attributes.forEach((childAttribute) => {
                            $this.expandChildEntityAttribute(childAttribute);
                            if (childAttribute.DataTypeKind === 1)
                                childAttribute.isLoading = false;
                        });
                    }
                    tab.mainTableLoading = false;
                }
            };
            callback.call(this);
        },
        //自动收缩
        autoCollapseEntityTable(tab, attribute) {
            let $this = this;
            if (attribute) {
                $this.collapseChildEntityAttribute(attribute);
            } else {
                tab.metedata.Attributes.forEach((childAttribute) => {
                    $this.collapseChildEntityAttribute(childAttribute);
                });
            }
        },
        //行双击事件
        onEntityAttributeDblClick(attribute, column, event) {
            if (!attribute || !attribute.hasChildren) return;
            let $this = this;
            let rowRefs = $this.$refs[attribute.attributeID];
            if (!rowRefs || !rowRefs.length || rowRefs.length === 0) return;
            let rowRef = rowRefs[0];
            if (!rowRef) return;
            const list = rowRef.parentNode.querySelectorAll(".el-table__expand-icon");
            if (list.length > 0)
                list[0].click();
        },
        //选择显示行
        selectDisplayLines(tab, selected) {
            let tableRefs = this.$refs[tab.name + '_EntityTableAttributesRef'];
            if (!tableRefs || !tableRefs.length || tableRefs.length === 0) return;
            let tableRef = tableRefs[0];
            let rowRefs = tableRef.$el.querySelectorAll(".el-table__row");
            rowRefs.forEach((rowRef) => {
                if (rowRef.style.display === 'none' || rowRef.className.includes("tablerow-hidden"))
                    return;
                let attribute = rowRef.__vue__.row;
                let index = tableRef.selection ? tableRef.selection.indexOf(attribute) : -1;
                if (selected) {
                    if (index < 0)
                        tableRef.toggleRowSelection(attribute, true);
                }
                else {
                    if (index >= 0)
                        tableRef.selection.splice(index);
                }
            });
        },
        //选择下级节点
        selectLowerLevelLines(tab, attribute, selected, isNextLevel) {
            if (!attribute) return;
            if (!attribute.children || attribute.children.length === 0) return;
            let tableRefs = this.$refs[tab.name + '_EntityTableAttributesRef'];
            if (!tableRefs || !tableRefs.length || tableRefs.length === 0) return;
            let tableRef = tableRefs[0];
            let $this = this;
            attribute.children.forEach((childAttribute) => {
                let index = tableRef.selection ? tableRef.selection.indexOf(childAttribute) : -1;
                if (selected) {
                    if (index < 0)
                        tableRef.toggleRowSelection(childAttribute, true);
                }
                else {
                    if (index >= 0)
                        tableRef.selection.splice(index, 1);
                }
                if (isNextLevel) {
                    $this.selectLowerLevelLines(tab, childAttribute, selected, isNextLevel);
                }
            });
        },
        //当实体属性右键点击
        onEntityAttributeRowRightClick(tab, row, column, event) {
            //console.log(arguments);
            event.preventDefault();
            let mainRefs = this.$refs[tab.name + '_main'];
            if (!mainRefs || !mainRefs.length || mainRefs.length === 0) return;
            let tableRefs = this.$refs[tab.name + '_EntityTableAttributesRef'];
            if (!tableRefs || !tableRefs.length || tableRefs.length === 0) return;
            let mainRef = mainRefs[0];
            let tableRef = tableRefs[0];
            let menu = mainRef.$el.querySelector(".tableRightMenuDiv");
            if (!menu) return;
            menu.style.display = "block";
            let left = event.clientX + 10;
            let top = event.clientY - 45;
            if (left + menu.clientWidth > document.body.clientWidth) {
                left = event.clientX - menu.clientWidth - 10;
                if (left < 0) left = 0;
            }
            if (top + menu.clientHeight > document.body.clientHeight) {
                top = document.body.clientHeight - menu.clientHeight - 60;
                if (top < 0) top = 0;
            }
            menu.style.left = `${left}px`;
            menu.style.top = `${top}px`;
            tableRef.setCurrentRow(row);
            tab.currentAttribute = row;
        },
        // table的左键点击当前行事件
        onEntityAttributeRowClick(tab, row, column, event) {
            let mainRefs = this.$refs[tab.name + '_main'];
            if (!mainRefs || !mainRefs.length || mainRefs.length === 0) return;
            let mainRef = mainRefs[0];
            let menu = mainRef.$el.querySelector(".tableRightMenuDiv");
            if (!menu) return;
            menu.style.display = "none";
            tab.currentAttribute = row;
        },
        //点击右键菜单
        onClickTableRightMenu(tab, command) {
            let tableRefs = this.$refs[tab.name + '_EntityTableAttributesRef'];
            if (!tableRefs || !tableRefs.length || tableRefs.length === 0) return;
            let tableRef = tableRefs[0];
            let mainRefs = this.$refs[tab.name + '_main'];
            if (!mainRefs || !mainRefs.length || mainRefs.length === 0) return;
            let mainRef = mainRefs[0];
            let menu = mainRef.$el.querySelector(".tableRightMenuDiv");
            if (!menu) return;
            menu.style.display = "none";
            if (!tab.currentAttribute) return;
            if (command === "expandAll") {
                this.autoExpandEntityTable(tab, tab.currentAttribute);
            }
            if (command == "collapseAll") {
                this.autoCollapseEntityTable(tab, tab.currentAttribute);
            }
            if (command === "selectDisplayLines") {
                this.selectDisplayLines(tab, true);
            }
            if (command === "unSelectDisplayLines") {
                this.selectDisplayLines(tab, false);
            }
            if (command === "selectLowerLevelLines") {
                this.selectLowerLevelLines(tab, tab.currentAttribute, true);
            }
            if (command === "unSelectLowerLevelLines") {
                this.selectLowerLevelLines(tab, tab.currentAttribute, false);
            }
            if (command === "selectAllLowerLevelLines") {
                this.selectLowerLevelLines(tab, tab.currentAttribute, true, true);
            }
            if (command === "unSelectAllLowerLevelLines") {
                this.selectLowerLevelLines(tab, tab.currentAttribute, false, true);
            }
        },
        //收缩所有子属性
        collapseChildEntityAttribute(attribute) {
            let $this = this;
            let rowRefs = $this.$refs[attribute.attributeID];
            if (!rowRefs || !rowRefs.length || rowRefs.length === 0) return;
            let rowRef = rowRefs[0];
            if (!rowRef) return;
            const list = rowRef.parentNode.querySelectorAll(".el-table__expand-icon");
            if (list.length > 0 && list[0].className.includes("el-table__expand-icon--expanded"))
                list[0].click();
            $this.$nextTick(() => {
                if (attribute.children && attribute.children.length > 0) {
                    attribute.children.forEach((childAttribute) => {
                        if (childAttribute.hasChildren)
                            $this.collapseChildEntityAttribute(childAttribute);
                    });
                }
            });
        },
        //展开属性的子属性
        expandChildEntityAttribute(attribute) {
            if (attribute.DataTypeKind !== 1) return;
            let $this = this;
            let rowRefs = $this.$refs[attribute.attributeID];
            if (!rowRefs || !rowRefs.length || rowRefs.length === 0) return;
            let rowRef = rowRefs[0];
            const list = rowRef.parentNode.querySelectorAll(".el-table__expand-icon");
            if (list.length > 0 && !list[0].className.includes("el-table__expand-icon--expanded"))
                list[0].click();
            $this.$nextTick(() => {
                if (attribute.children && attribute.children.length > 0) {
                    attribute.children.forEach((childAttribute) => {
                        if (childAttribute.DataTypeKind === 1)
                            $this.expandChildEntityAttribute(childAttribute);
                    });
                }
            });
        },
        loadChildEntityAttribute(attribute, needExpandAttributes) {
            if (attribute.DataTypeKind !== 1) return;
            let $this = this;
            if (attribute.children && attribute.children.length > 0) {
                attribute.children.forEach((childAttribute) => {
                    if (childAttribute.DataTypeKind === 1)
                        $this.loadChildEntityAttribute(childAttribute, needExpandAttributes);
                });
            }
            else {
                //实体或属性
                let keyID = attribute.DataTypeKey.ID;
                let needExpandAttribute = { id: attribute.attributeID, name: attribute.Name, loading: true };
                needExpandAttributes.push(needExpandAttribute);
                this.getCloneMetedata(keyID, NaN, function (metedata) {
                    let currentMetedata = metedata;
                    //补齐Entity元数据
                    $this.patchEntityMetedata(currentMetedata, attribute);
                    attribute.children = currentMetedata.Attributes;
                    attribute.children.forEach((childAttribute) => {
                        if (childAttribute.DataTypeKind === 1)
                            $this.loadChildEntityAttribute(childAttribute, needExpandAttributes);
                    });
                    needExpandAttribute.loading = false;
                })
            }
        },
        //获当前属性的OQL表达式
        getAttributeOQLExpressions() {
            if (!this.popover.oqlExpressionActiveAttribute) return [];
            if (!this.oqlExpressions) return [];
            let $this = this;
            let expressions = [];
            this.oqlExpressions.forEach((typeExpression, index) => {
                if (!typeExpression.filter || typeExpression.filter.call($this, this.popover.oqlExpressionActiveAttribute)) {
                    typeExpression.expressions.forEach((expression, index) => {
                        if (!expression.filter || expression.filter.call($this, this.popover.oqlExpressionActiveAttribute)) {
                            if (expression.SQLType && typeof expression.SQLType === "function") {
                                expression.type = expression.SQLType.call($this, this.popover.oqlExpressionActiveAttribute);
                            } else {
                                expression.type = expression.SQLType;
                            }
                            expressions.push(expression);
                        }
                    })
                }
            })
            return expressions;
        },
        //当OQL表达式弹出窗选择发生变化
        onOqlExpressionPopoverSelectChange(selection) {
            if (!this.$refs.oqlExpressionPopover) return;
            if (!this.$refs.oqlExpressionPopover.showPopper) return;
            if (!this.popover.oqlExpressionActiveAttribute) return;
            let attribute = this.popover.oqlExpressionActiveAttribute;
            attribute.oqlExpressions = selection;
            let tab = attribute.metedata.tab;
            let tableRefs = this.$refs[tab.name + '_EntityTableAttributesRef'];
            if (!tableRefs || !tableRefs.length || tableRefs.length === 0) return;
            let tableRef = tableRefs[0];
            let selected = selection && selection.length > 0;
            let index = tableRef.selection ? tableRef.selection.indexOf(attribute) : -1;
            if (selected) {
                if (index < 0)
                    tableRef.toggleRowSelection(attribute, true);
            }
            else {
                if (index >= 0)
                    tableRef.selection.splice(index, 1);
            }
        },
        //当属性OQL表达式点击时
        onAttributeFormulaExpressionClick(attribute) {
            if (this.popover.formulaExpressionActiveAttribute == attribute
                && this.$refs.formulaExpressionPopover.showPopper) return;
            let attrRefs = this.$refs[attribute.attributeID + '_AttributeFormulaExpression'];
            if (!attrRefs || !attrRefs.length || attrRefs.length === 0) return;
            let attrRef = attrRefs[0];
            this.popover.formulaExpressionShow = false;
            this.popover.formulaExpressionActiveAttribute = attribute;
            this.popover.formulaExpressionActiveReference = attrRef.$el;
            let $this = this;
            this.$nextTick(() => {
                $this.popover.formulaExpressionShow = true;
                $this.$nextTick(() => {
                    $this.$refs.formulaExpressionPopover.doShow();
                    if (attribute.formulaExpressions && attribute.formulaExpressions.length > 0) {
                        attribute.formulaExpressions.forEach((formulaExpression, index) => {
                            $this.$refs.formulaExpressionTable.toggleRowSelection(formulaExpression, true);
                        });
                    }
                })
            })
        },
        //获当前属性的公式表达式
        getAttributeFormulaExpressions() {
            if (!this.popover.formulaExpressionActiveAttribute) return [];
            if (!this.formulaExpressions) return [];
            let $this = this;
            let expressions = [];
            this.formulaExpressions.forEach((typeExpression, index) => {
                if (!typeExpression.filter || typeExpression.filter.call($this, this.popover.formulaExpressionActiveAttribute)) {
                    typeExpression.expressions.forEach((expression, index) => {
                        if (!expression.filter || expression.filter.call($this, this.popover.formulaExpressionActiveAttribute))
                            expressions.push(expression);
                    })
                }
            })
            return expressions;
        },
        //当公式表达式弹出窗选择发生变化
        onFormulaExpressionPopoverSelectChange(selection) {
            if (!this.$refs.formulaExpressionPopover) return;
            if (!this.$refs.formulaExpressionPopover.showPopper) return;
            if (!this.popover.formulaExpressionActiveAttribute) return;
            let attribute = this.popover.formulaExpressionActiveAttribute;
            attribute.formulaExpressions = selection;
        },
        //树形表格过滤
        hasChildEntityTreeData(attributes, filterString, filterOperatorType, filterClassType) {
            if (!attributes || attributes.length === 0) return false;
            let $this = this;
            for (const attribute of attributes) {
                let match = $this.isTableRowMatch(attribute, filterString, filterOperatorType, filterClassType);
                if (match || $this.hasChildEntityTreeData(attribute.children, filterString, filterOperatorType, filterClassType))
                    return true;
            }
            return false;
        },
        //是否父属性符合条件
        isTableRowAndParentTableRowMatch(attribute, filterString, filterOperatorType, filterClassType) {
            if (!attribute.parentAttribute)
                return this.isTableRowMatch(attribute, filterString, filterOperatorType, filterClassType);
            return this.isTableRowAndParentTableRowMatch(attribute.parentAttribute, filterString, filterOperatorType, filterClassType);
        },
        //Table Row 是否符合条件
        isTableRowMatch(attribute, filterString, filterOperatorType, filterClassType) {
            if (filterClassType && filterClassType.indexOf(-1) < 0 && filterClassType.indexOf(attribute.DataTypeFlag) < 0)
                return false;
            if (!filterString || filterString.length === 0) return true;
            if (!filterOperatorType) filterOperatorType = 0;
            if (filterOperatorType === 0)
                return attribute.Name.toLowerCase().startsWith(filterString) ||
                    attribute.DisplayName.toLowerCase().startsWith(filterString);
            if (filterOperatorType === 1)
                return attribute.Name.toLowerCase().includes(filterString) ||
                    attribute.DisplayName.toLowerCase().includes(filterString);
            if (filterOperatorType === 2)
                return attribute.Name.toLowerCase().endsWith(filterString) ||
                    attribute.DisplayName.toLowerCase().endsWith(filterString);
            if (filterOperatorType === 3)
                return attribute.Name.toLowerCase() === filterString ||
                    attribute.DisplayName.toLowerCase() === filterString;
        },
        //行层索引
        onRowIndexClick(tab, attribute, level) {
            if (!tab || !attribute || !level) return;
            if (attribute.level === level) return;
            let fullExpression = attribute.fullExpression;
            let exprArr = fullExpression.split('.');
            let levelFullExpression = exprArr.slice(0, level + 1).join('.');
            let metedata = tab.metedata;
            let mainRefs = this.$refs[metedata.Key.ID + '_main'];
            if (!mainRefs || !mainRefs.length || mainRefs.length === 0) return;
            let mainRef = mainRefs[0];
            let tableRefs = this.$refs[metedata.Key.ID + '_EntityTableAttributesRef'];
            if (!tableRefs || !tableRefs.length || tableRefs.length === 0) return;
            let tabRef = tableRefs[0];
            let dom = mainRef.$el;
            let exprAttribute = this.getAttributeByExpression(attribute, levelFullExpression);
            if (!exprAttribute) return;
            let rowRefs = this.$refs[attribute.attributeID];
            if (!rowRefs || !rowRefs.length || rowRefs.length === 0) return;
            let rowRef = rowRefs[0];
            let targetRowRefs = this.$refs[exprAttribute.attributeID];
            if (!targetRowRefs || !targetRowRefs.length || targetRowRefs.length === 0) return;
            let targetRowRef = targetRowRefs[0];
            this.$nextTick(() => {
                var top1 = this.getElementTop(rowRef);
                var top2 = this.getElementTop(targetRowRef);
                dom.scrollTo({
                    top: top2 - 60,
                    behavior: "smooth"
                });
                tabRef.setCurrentRow(exprAttribute);
            });
        },
        //获取行索引显示字符
        getRowIndexViewString(tab, attribute, level) {
            if (!tab || !attribute || !level) return;
            let fullExpressionDisplayName = attribute.fullExpressionDisplayName;
            let names = fullExpressionDisplayName.split(".");
            return names.slice(0, level + 1).join(".");
        },
        //焦点行
        focusAttribute(tab, attribute) {
            tab.filterParameter.filterClassType = [-1];
            tab.filterParameter.confirmFilterString = "";
            let metedata = tab.metedata;
            let mainRefs = this.$refs[metedata.Key.ID + '_main'];
            if (!mainRefs || !mainRefs.length || mainRefs.length === 0) return;
            let mainRef = mainRefs[0];
            let tableRefs = this.$refs[metedata.Key.ID + '_EntityTableAttributesRef'];
            if (!tableRefs || !tableRefs.length || tableRefs.length === 0) return;
            let tabRef = tableRefs[0];
            let dom = mainRef.$el;
            let rowRefs = this.$refs[attribute.attributeID];
            if (!rowRefs || !rowRefs.length || rowRefs.length === 0) return;
            let rowRef = rowRefs[0];
            let targetRowRefs = this.$refs[attribute.attributeID];
            if (!targetRowRefs || !targetRowRefs.length || targetRowRefs.length === 0) return;
            let targetRowRef = targetRowRefs[0];
            this.$nextTick(() => {
                var top1 = this.getElementTop(rowRef);
                var top2 = this.getElementTop(targetRowRef);
                dom.scrollTo({
                    top: top2 - 60,
                    behavior: "smooth"
                });
                tabRef.setCurrentRow(attribute);
            });
        },
        //通过表达式获取属性
        getAttributeByExpression(attribute, fullExpression) {
            if (!attribute || !fullExpression) return NaN;
            if (attribute.fullExpression == fullExpression) return attribute;
            if (!attribute.parentAttribute) return NaN;
            return this.getAttributeByExpression(attribute.parentAttribute, fullExpression);
        },
        getElementTop(element) {
            let actualTop = element.offsetTop;
            let current = element.offsetParent;
            while (current !== null) {
                actualTop += current.offsetTop;
                current = current.offsetParent;
            }
            return actualTop;
        },
        //收缩属性
        collapseEntityMetedataAttributes(metedata, attributes, tabRef) {
            if (!tabRef) {
                let tabRefs = this.$refs[metedata.Key.ID + '_EntityTableAttributesRef'];
                if (!tabRefs || !tabRefs.length || tabRefs.length === 0) return;
                tabRef = tabRefs[0];
            }
            if (!attributes) attributes = metedata.Attributes;
            let $this = this;
            //tab.expandrowkeys = [];
            attributes.forEach((item) => {
                if (item.children && item.children.length > 0) {
                    $this.collapseEntityMetedataAttributes(metedata, item.children, tabRef);
                }
                tabRef.toggleRowExpansion(item, false);
            });
        },
        //#endregion
        //#region BPSV
        //初始化Json编辑器
        initBPSVEditor(tab, proxyJsonString) {
            let $this = this;
            require(['vs/editor/editor.main'], function () {
                let cfg = $this.getEditorConfig('json');
                let requestEditorRefs = $this.$refs[tab.metedata.Key.ID + '_requestEditor'];
                if (requestEditorRefs && requestEditorRefs.length && requestEditorRefs.length > 0) {
                    let editor = monaco.editor.create(requestEditorRefs[0], cfg);
                    tab.editor = editor;
                    setTimeout(function () {
                        if (proxyJsonString) {
                            $this.setJsonEditorValue(editor, proxyJsonString);
                        }
                        else {
                            $this.getProxyData(tab);
                        }
                    }, 100);
                }
                let resultEditorRefs = $this.$refs[tab.metedata.Key.ID + '_resultEditor'];
                if (resultEditorRefs && resultEditorRefs.length && resultEditorRefs.length > 0) {
                    let editor = monaco.editor.create(resultEditorRefs[0], cfg);
                    tab.resulteditor = editor;
                    // let keyID = tab.metedata.Key.ID;
                    // $this.getCloneMetedata(keyID, NaN, function (metedata) {
                    //     setTimeout(function () {
                    //         editor.setValue(JSON.stringify(metedata));
                    //         editor.trigger('anyString', 'editor.action.formatDocument');
                    //         editor.setValue(editor.getValue());
                    //     }, 100);
                    // })
                }
            })
        },
        //给Json编码辑赋值
        setJsonEditorValue(editor, json) {
            editor.setValue(json);
            editor.trigger('anyString', 'editor.action.formatDocument');
            editor.setValue(editor.getValue());
        },
        //加载代理数据
        getProxyData(tab) {
            let editor = tab.editor;
            let $this = this;
            tab.proxyAction.loadProxyDataLoading = true;
            this.api().getProxyData(tab.proxyParameter, function (res) {
                if (res.code === 0) {
                    //console.log('proxyData', JSON.stringify(res.data))
                    $this.setJsonEditorValue(editor, res.data.ProxyJsonString);
                    tab.proxyAction.loadProxyDataLoading = false;
                } else {
                    $this.$notify.error({
                        title: '错误',
                        message: res && res.msg ? res.msg : '未知',
                        duration: 1000
                    });
                }
            });
        },
        //累计重载
        totalLoadProxyData(tab) {
            let editor = tab.editor;
            let oldJsonString = editor.getValue();
            let selectionRange = editor.getSelection();
            //选中位置如果是特定字符,自动替换
            if (selectionRange) {
                let selectionText = editor.getModel().getValueInRange(selectionRange);
                if (selectionText === "null")
                    editor.executeEdits(selectionText, [{ "range": selectionRange, "text": "{}" }]);
                if (selectionText === "[],")
                    editor.executeEdits(selectionText, [{ "range": selectionRange, "text": "[{}]," }]);
            }
            let $this = this;
            tab.proxyAction.totalLoadProxyDataLoading = true;
            let currPosition = editor.getPosition();
            let parameter = {
                ...tab.proxyParameter,
                proxyJsonString: editor.getValue()
            };
            this.api().totalGetProxyData(parameter, function (res) {
                if (res.code === 0) {
                    console.log('proxyData', JSON.stringify(res.data))
                    let data = res.data;
                    editor.setValue(data.ProxyJsonString);
                    editor.trigger('anyString', 'editor.action.formatDocument');
                    editor.setValue(editor.getValue());
                    setTimeout(function () {
                        editor.revealPositionNearTop(currPosition);
                    }, 200);
                }
                else {
                    editor.setValue(oldJsonString);
                }

                tab.proxyAction.totalLoadProxyDataLoading = false;
            });
        },
        //服务调试的命令
        handleBPSVDebugCommand(tab, command) {
            if (command == "clear") {
                this.handleTransactionDebugCommand(tab, command);
            }
            if (command === "global") {
                this.handleTransactionDebugCommand(tab, command);
            }
            if (command === "proxy") {
                this.handleTransactionDebugCommand(tab, command);
            }
            if (command === "interceptProxyData") {
                this.proxyDoDebug(tab);
            }
        },
        //事务调试的命令
        handleTransactionDebugCommand(tab, command) {
            if (!tab) return;
            let $this = this;
            if (command == "clear") {
                tab.transactionDebug.logData = [];
                return;
            }
            let isSetup = false;
            if (command === "global") {
                isSetup = !tab.transactionDebug.isSetupGlobal;
            }
            if (command === "proxy") {
                isSetup = !tab.transactionDebug.isSetupProxy;
            }
            this.closeTransactionDebug(tab);
            if (isSetup) {
                this.api().setupTransactionDebug(function (res) {
                    if (res.code === 0) {
                        let wsUrl = 'ws://' + window.location.host + ':' + res.data.port + res.data.path;
                        if (command === "proxy")
                            wsUrl = wsUrl + '?proxyType=' + encodeURIComponent(tab.proxyParameter.proxyFullName + "," + tab.proxyParameter.proxyAssemblyName);
                        let webSocket = new WebSocket(wsUrl);
                        webSocket.onopen = function (event) {
                            console.log("transactionDebug connect successfully")
                            tab.transactionDebug.webSocket = webSocket;
                            if (command === "global") {
                                tab.transactionDebug.isSetupGlobal = true;
                            }
                            if (command === "proxy") {
                                tab.transactionDebug.isSetupProxy = true;
                            }
                        };
                        webSocket.onmessage = function (event) {
                            const message = event.data;
                            //处理从服务器接收的消息
                            console.log('Received message:', message);
                            let data = JSON.parse(message);
                            tab.transactionDebug.logData.unshift(data);
                        };
                        webSocket.onclose = function (event) {
                            $this.closeTransactionDebug(tab);
                            console.log("transactionDebug close successfully")
                        };
                    } else {
                        $this.$notify.error({
                            title: '错误',
                            message: res && res.msg ? res.msg : '未知',
                            position: 'bottom-right',
                            duration: 3000
                        });
                    }
                });
            }
        },
        //关闭事务调试
        closeTransactionDebug(tab) {
            if (tab.transactionDebug.webSocket && tab.transactionDebug.webSocket.readyState === 1)
                tab.transactionDebug.webSocket.close();
            tab.transactionDebug.webSocket = NaN;
            tab.transactionDebug.isSetupGlobal = false;
            tab.transactionDebug.isSetupProxy = false;
        },
        //其它操作菜单命令
        handleBPSVTestOtherCommand(tab, command) {
            if (command == "copyRequestData") {
                this.copyRequestData(tab);
            }
            if (command == "copyWSSRequestData") {
                this.copyWSSRequestData(tab);
            }
            if (command == "copyWSSRequestDataWithContext") {
                this.copyWSSRequestData(tab, true);
            }
            if (command === "copyResultData") {
                this.copyResultData(tab);
            }
            if (command === "saveWSSRequestDataFile") {
                this.saveWSSRequestDataFile(tab);
            }
            if (command === "saveWSSRequestDataFileWithContext") {
                this.saveWSSRequestDataFile(tab, true);
            }
            if (command === "linkToWSS") {
                this.linkToWSS();
            }
        },
        //发送代理请求
        sendProxyReqeust(tab) {
            let editor = tab.editor;
            let resulteditor = tab.resulteditor;
            let $this = this;
            tab.proxyAction.proxyDoLoading = true;
            let parameter = {
                ...tab.proxyParameter,
                proxyJsonString: editor.getValue()
            };
            this.api().proxyDo(parameter, function (res) {
                if (res.code === 0) {
                    let returnJsonString = res.data;
                    console.log('proxyData', returnJsonString)
                    resulteditor.setValue(returnJsonString);
                    resulteditor.trigger('anyString', 'editor.action.formatDocument');
                    resulteditor.setValue(resulteditor.getValue());
                    tab.currentBPSVTabIndex = 'bpsvTabMainTestResultTab';
                }
                else {
                    resulteditor.setValue('');
                    $this.$notify.error({
                        title: '错误',
                        message: res && res.msg ? res.msg : '未知',
                        position: 'bottom-right',
                        duration: res.code === 1 ? 1000 : 5000
                    });
                }
                tab.proxyAction.proxyDoLoading = false;
            });
        },
        //拦截数据
        proxyDoDebug(tab) {
            let $this = this;
            let isSetup = !tab.proxyDoDebug.proxyDoDebugLoading;
            if (isSetup) {
                this.api().setupProxyDoDebug(function (res) {
                    if (res.code === 0) {
                        let wsUrl = 'ws://' + window.location.host + ':' + res.data.port + res.data.path;
                        wsUrl = wsUrl + '?proxyType=' + encodeURIComponent(tab.proxyParameter.proxyFullName + "," + tab.proxyParameter.proxyAssemblyName);
                        let webSocket = new WebSocket(wsUrl);
                        webSocket.onopen = function (event) {
                            console.log("proxyDoDebug connect successfully")
                            tab.proxyDoDebug.webSocket = webSocket;
                            tab.proxyDoDebug.proxyDoDebugLoading = true;
                        };
                        webSocket.onmessage = function (event) {
                            const message = event.data;
                            //处理从服务器接收的消息
                            console.log('Received message:', message);
                            let data = JSON.parse(message);
                            if (!data) return;
                            if (data.proxyFullName !== tab.proxyParameter.proxyFullName || data.proxyAssemblyName !== tab.proxyParameter.proxyAssemblyName) return;
                            if (data.requestData) {
                                $this.$confirm('拦截到请求数据,是否加载?', '提示', {
                                    confirmButtonText: '加载',
                                    cancelButtonText: '取消',
                                    type: 'info'
                                }).then(() => {
                                    let editor = tab.editor;
                                    editor.setValue(data.requestData);
                                    editor.trigger('anyString', 'editor.action.formatDocument');
                                    editor.setValue(editor.getValue());
                                    tab.currentBPSVTabIndex = 'bpsvTabMainTestRequestTab';
                                }).catch(() => {
                                    console.log("取消");
                                });
                            }
                            if (data.resultData) {
                                $this.$confirm('拦截到返回数据,是否加载?', '提示', {
                                    confirmButtonText: '加载',
                                    cancelButtonText: '取消',
                                    type: 'info'
                                }).then(() => {
                                    let editor = tab.resulteditor;
                                    editor.setValue(data.resultData);
                                    editor.trigger('anyString', 'editor.action.formatDocument');
                                    editor.setValue(editor.getValue());
                                    tab.currentBPSVTabIndex = 'bpsvTabMainTestResultTab';
                                }).catch(() => {
                                    console.log("取消");
                                });
                            }

                        };
                        webSocket.onclose = function (event) {
                            $this.closeProxyDoDebug(tab);
                            console.log("proxyDoDebug close successfully")
                        };
                    } else {
                        $this.$notify.error({
                            title: '错误',
                            message: res && res.msg ? res.msg : '未知',
                            position: 'bottom-right',
                            duration: 3000
                        });
                    }
                });
            }
            else {
                $this.closeProxyDoDebug(tab);
            }
        },
        //关闭拦截数据
        closeProxyDoDebug(tab) {
            if (tab.proxyDoDebug.webSocket && tab.proxyDoDebug.webSocket.readyState === 1)
                tab.proxyDoDebug.webSocket.close();
            tab.proxyDoDebug.webSocket = NaN;
            tab.proxyDoDebug.proxyDoDebugLoading = false;
        },
        //复制请求数据
        copyRequestData(tab) {
            let editor = tab.editor;
            this.copyToClipboard(editor.getValue());
        },
        //复制WSS请求数据
        copyWSSRequestData(tab, withContext) {
            this.copyToClipboard(this.createWSSRequestData(tab, withContext));
        },
        //保存WSS文件
        saveWSSRequestDataFile(tab, withContext) {
            let blob = new Blob([this.createWSSRequestData(tab, withContext)], { type: "text/plain;charset=utf-8" });
            let fileName = tab.openBPSVFileName && tab.openBPSVFileName.length > 0 ?
                tab.openBPSVFileName : (tab.title + ".json");
            saveAs(blob, fileName);
        },
        //连接WSS
        linkToWSS() {
            window.open('https://gitee.com/mutongtech/wss', "_blank")
        },
        //创建WSS请求数据
        createWSSRequestData(tab, withContext) {
            let editor = tab.editor;
            let data = {};
            if (withContext) data.context = this.createWSSContext();
            data.proxy = tab.proxyParameter.proxyFullName.concat(",")
                .concat(tab.proxyParameter.proxyAssemblyName);
            let jsonString = editor.getValue();
            if (!jsonString || jsonString.length === 0) {
                data.data = {};
            }
            else {
                try {
                    data.data = JSON.parse(jsonString);
                }
                catch (err) {
                    console.log("createWSSRequestData err:", err);
                    data.data = jsonString;
                }
            }
            return JSON.stringify(data, null, "\t");
        },
        //创建WSS的上下文
        createWSSContext() {
            let contextData = this.index.contextData;
            if (!contextData) return null;
            return {
                enterpriseID: contextData.EnterpriseID,
                orgCode: contextData.OrgCode,
                userCode: contextData.UserCode,
                password: "",
                culture: contextData.Culture,
                supportCultureNameList: contextData.Support_CultureName_List
            };
        },
        //复制返回数据
        copyResultData(tab) {
            let editor = tab.resulteditor;
            this.copyToClipboard(editor.getValue());
        },
        //获取事务类型数组
        getTransactionTypeOptions() {
            let options = [];
            this.enums.transactionTypeOptions.forEach((option, index) => {
                options.push({ text: option.name, value: option.value });
            });
            return options;
        },
        //事务类型过滤
        filterTransactionTypeHandler(value, row, column) {
            const property = column['property'];
            return row[property] === value;
        },
        //#endregion
        //#region OQL
        //初始化OQL编辑器
        initOQLEditor(tab, oql) {
            let $this = this;
            require(['vs/editor/editor.main'], function () {
                let oqlEditorRefs = $this.$refs[tab.name + '_OQLEditor'];
                if (oqlEditorRefs && oqlEditorRefs.length && oqlEditorRefs.length > 0) {
                    let cfg = $this.getEditorConfig('sql', oql);
                    let editor = monaco.editor.create(oqlEditorRefs[0], cfg);
                    tab.OQLEditor = editor;
                    editor.isOQL = true;
                }
                let sqlEditorRefs = $this.$refs[tab.name + '_SQLEditor'];
                if (sqlEditorRefs && sqlEditorRefs.length && sqlEditorRefs.length > 0) {
                    let cfg = $this.getEditorConfig('sql');
                    let editor = monaco.editor.create(sqlEditorRefs[0], cfg);
                    tab.SQLEditor = editor;
                }
            })
        },
        //通过实体Tab生成OQL
        createOQLFromEntityTab(tab, oqlParameter) {
            if (!tab) return;
            let $this = this;
            let metedata = tab.metedata;
            let tableRefs = this.$refs[tab.name + '_EntityTableAttributesRef'];
            if (!tableRefs || !tableRefs.length || tableRefs.length === 0) return;
            let tabRef = tableRefs[0];
            let selectedRows = tabRef.selection;
            //按行号排列
            let sortSelectedRows = selectedRows.concat();
            sortSelectedRows.sort((a, b) => {
                return a.rowIndex > b.rowIndex ? 1 : -1;
            })
            if (oqlParameter && oqlParameter.sortFieldByRowIndex) {
                selectedRows = sortSelectedRows.concat();
            }
            //关联
            let expandEntityTable = oqlParameter && oqlParameter.expandEntityTable;
            let associationAttributes = [];
            let treeElements = [];
            let allElements = [];
            if (expandEntityTable) {
                //找出所有关联的属性
                sortSelectedRows.forEach((attribute, index) => {
                    if (attribute.parentAttribute)
                        $this.addAttributeInAssociationAttributes(associationAttributes, attribute.parentAttribute);
                });
                //构建树
                let treeElement;
                associationAttributes.forEach((attribute, index) => {
                    let parentAttribute = this.getAttributeEntityParentAttribute(attribute);
                    if (!parentAttribute) {
                        treeElement = {
                            attribute: attribute,
                            tableAliasName: attribute.fullExpression.replace(/\./g, "_"),
                            childElements: []
                        };
                        treeElements.push(treeElement);
                        allElements.push(treeElement);
                    } else {
                        this.createAttributeTreeElement(allElements, treeElement, attribute);
                    }
                });
            }
            let oqls = ["select "];
            let isFirst = true;
            let displayNames = [];
            if (selectedRows && selectedRows.length > 0) {
                selectedRows.forEach((attribute, index) => {
                    if (attribute.DataTypeFlag !== 2 && attribute.DataTypeFlag !== 4) {
                        let displayName = oqlParameter && oqlParameter.useEngcolumnAliasName ?
                            attribute.fullExpression : attribute.fullExpressionDisplayName;
                        displayName = displayName.replace(/[\.\-(－＿（]/g, "_");
                        displayName = $this.removeSpecialChar(displayName);
                        if (!isFirst) {
                            oqls.push(",");
                        }
                        oqls.push("\r\n", "  ");
                        let i = 0;
                        let tempDisplayName = displayName;
                        while (true) {
                            if (displayNames.indexOf(displayName) < 0) break;
                            i++;
                            displayName = tempDisplayName.concat(i);
                        }
                        displayNames.push(displayName);
                        isFirst = false;
                        let sqlFieldName;
                        let parentElement;
                        if (expandEntityTable) {
                            parentElement = this.getAttributeParentTreeElement(allElements, attribute);
                            if (parentElement) {
                                sqlFieldName = parentElement.tableAliasName +
                                    attribute.fullExpression.slice(parentElement.attribute.fullExpression.length)
                            }
                            else {
                                sqlFieldName = attribute.fullExpression;
                            }
                        } else {
                            sqlFieldName = attribute.fullExpression;
                        }
                        oqls.push(sqlFieldName, ' as ', displayName);
                        if (attribute.oqlExpressions && attribute.oqlExpressions.length > 0) {
                            attribute.oqlExpressions.forEach((oqlExpression, index) => {
                                oqls.push(",", "\r\n", "  ");
                                let expressionDisplayName = displayName.concat("_",
                                    $this.removeSpecialChar(oqlParameter && oqlParameter.useEngcolumnAliasName ?
                                        oqlExpression.code : oqlExpression.name));
                                let tempExpressionDisplayName = expressionDisplayName;
                                let i = 0;
                                while (true) {
                                    if (displayNames.indexOf(expressionDisplayName) < 0) break;
                                    i++;
                                    expressionDisplayName = tempExpressionDisplayName.concat(i);
                                }
                                displayNames.push(expressionDisplayName);
                                let expressionSQLFieldName = oqlExpression.expression(attribute);
                                if (expandEntityTable && parentElement) {
                                    expressionSQLFieldName = expressionSQLFieldName.replace(
                                        new RegExp(attribute.fullExpression.slice(0, parentElement.attribute.fullExpression.length), 'g'),
                                        parentElement.tableAliasName);
                                }
                                oqls.push(expressionSQLFieldName, ' as ', expressionDisplayName);
                            });
                        }
                    }
                });
            }
            else {
                oqls.push("\r\n", "  ", "* ");
            }
            oqls.push("\r\n", "from ");
            //主表
            oqls.push("\r\n", "  ", this.getEntityOQLFullName(metedata.Key.FullName), " ", metedata.Key.Name);
            //扩展子表
            if (expandEntityTable) {
                treeElements.forEach((treeElement, index) => {
                    this.addJoinTableInOql(oqls, treeElement, metedata.Key.Name);
                });
            }
            //where条件
            if (oqlParameter && oqlParameter.useBusinessKeyForParams) {
                oqls.push("\r\n", "where ");
                if (metedata.BKAttributes && metedata.BKAttributes.length > 0) {
                    metedata.BKAttributes.forEach((bkAttribute, index) => {
                        oqls.push("\r\n", "  ", index > 0 ? " and " : "", metedata.Key.Name, ".",
                            bkAttribute, " = ", "@", bkAttribute.replace(/\./g, "_"));
                    })
                } else {
                    oqls.push("\r\n", "  ", metedata.Key.Name, ".ID = @ID");
                }
            }
            return oqls.join("");
        },
        //执行OQL
        getOQLQueryResult(tab, pageIndex, pageSize) {
            if (typeof pageIndex !== "undefined")
                tab.runOQLResult.pageParamter.pageIndex = pageIndex;
            if (pageSize)
                tab.runOQLResult.pageParamter.pageSize = pageSize;
            let oqlEditor = tab.OQLEditor;
            let $this = this;
            tab.oqlAction.runOqlLoading = true;
            let pageParamter = tab.runOQLResult.pageParamter;
            this.api().runOQL(oqlEditor.getValue(), pageParamter, function (res) {
                if (res.code === 0) {
                    //console.log('queryResult', res.data)
                    tab.currentOQLTabIndex = 'oqlTabMainResultTab';
                    $this.$set(tab, 'runOQLResult', JSON.parse(res.data));
                }
                else {
                    $this.$notify.error({
                        title: '错误',
                        message: res && res.msg ? res.msg : '未知',
                        position: 'bottom-right',
                        duration: 6000
                    });
                }

                tab.oqlAction.runOqlLoading = false;
            });
        },
        //查询结果页大小变化
        handleOQLResultTableSizeChange(pageSize) {
            let $this = this;
            let tab = $this.tabs.find((item) => item.name == $this.currentTabIndex);
            if (!tab) return;
            this.getOQLQueryResult(tab, 0, pageSize);
        },
        //查询结果当前页变化
        handleOQLResultTableCurrentChange(pageIndex) {
            let $this = this;
            let tab = $this.tabs.find((item) => item.name == $this.currentTabIndex);
            if (!tab) return;
            this.getOQLQueryResult(tab, pageIndex - 1);
        },
        //获取执行OQL结果的所有列
        getRunOQLResultColumns(tab) {
            if (!tab || !tab.runOQLResult || !tab.runOQLResult.queryData) return [];
            let queryDatas = tab.runOQLResult.queryData;
            if (queryDatas.length === 0) return [];
            let queryData = queryDatas[0];
            let columns = [];
            for (const prop in queryData) {
                if (prop === '__Qry_RowNumber') continue;
                columns.push(prop);
            }
            return columns;
        },
        //获取执行OQL结果的格式
        runOQLResultFormatter(row, column, cellValue) {
            if (typeof cellValue === "boolean") return cellValue ? "true" : "false";
            return cellValue;
        },
        //表头部重新渲染
        renderRunOQLResultHeader(h, { column, $index }) {
            let span = document.createElement('span');
            span.innerText = column.label;
            document.body.appendChild(span);
            column.minWidth = span.getBoundingClientRect().width + 40;
            document.body.removeChild(span);
            return h('span', column.label);
        },
        //依据来源重构OQL
        createOQLBySrcTab(tab) {
            let oqlEditor = tab.OQLEditor;
            let oql;
            if (tab.srcTab.type == "entity")
                oql = this.createOQLFromEntityTab(tab.srcTab, tab.oqlParameter);
            if (tab.srcTab.type == "enum")
                oql = this.createOQLFromEnumTab(tab.srcTab);
            if (!oql) return;
            oqlEditor.setValue(oql);
            this.formatEditorValue(oqlEditor);
            tab.currentOQLTabIndex = 'oqlTabMainOQLTab';
        },
        //获取SQL
        getSQLByOQL(tab) {
            let oqlEditor = tab.OQLEditor;
            let sqlEditor = tab.SQLEditor;
            let $this = this;
            tab.oqlAction.convertOqlToSqlLoading = true;
            this.api().convertOqlToSql(oqlEditor.getValue(), function (res) {
                if (res.code === 0) {
                    let sql = res.data;
                    console.log('sql', sql)
                    if (tab.srcTab && tab.srcTab.type == "entity" && tab.oqlParameter
                        && tab.oqlParameter.createTempTableWhenCreateSQL) {
                        let tempTableSQL = $this.createTempTableSQL(tab.srcTab, tab.oqlParameter);
                        sql = tempTableSQL + "\r\n" + sql;
                    }
                    sqlEditor.setValue(sql);
                    $this.formatEditorValue(sqlEditor);
                    tab.currentOQLTabIndex = 'oqlTabMainSQLTab';
                    $this.$message({
                        message: '转换SQL成功',
                        type: 'success',
                        duration: 1000
                    });
                }
                else {
                    //sqlEditor.setValue('');
                    $this.$notify.error({
                        title: '错误',
                        message: res && res.msg ? res.msg : '未知',
                        position: 'bottom-right',
                        duration: 6000
                    });
                }
                tab.oqlAction.convertOqlToSqlLoading = false;
            });
        },
        //生成创建临时表SQL
        createTempTableSQL(tab, oqlParameter) {
            if (!tab || tab.type !== "entity") return "";
            let $this = this;
            let metedata = tab.metedata;
            let tableRefs = this.$refs[tab.name + '_EntityTableAttributesRef'];
            if (!tableRefs || !tableRefs.length || tableRefs.length === 0) return "";
            let tabRef = tableRefs[0];
            let selectedRows = tabRef.selection;
            if (!selectedRows || selectedRows.length === 0) return "";
            if (oqlParameter && oqlParameter.sortFieldByRowIndex) {
                selectedRows.sort((a, b) => {
                    return a.rowIndex > b.rowIndex ? 1 : -1;
                })
            }
            let oqls = ["IF OBJECT_ID('tempdb..#" + metedata.Name + "TempTable') IS NOT NULL"];
            oqls.push("\r\n", "  ", "DROP TABLE #" + metedata.Name + "TempTable;");
            oqls.push("\r\n", "CREATE TABLE #" + metedata.Name + "TempTable");
            oqls.push("\r\n", "(");
            let isFirst = true;
            let displayNames = [];
            selectedRows.forEach((attribute, index) => {
                if (attribute.DataTypeFlag !== 2 && attribute.DataTypeFlag !== 4) {
                    let displayName = oqlParameter && oqlParameter.useEngcolumnAliasName ?
                        attribute.fullExpression : attribute.fullExpressionDisplayName;
                    displayName = displayName.replace(/[\.\-(－＿（]/g, "_");
                    displayName = $this.removeSpecialChar(displayName);
                    if (!isFirst) oqls.push(",");
                    isFirst = false;
                    oqls.push("\r\n", "  ");
                    let i = 0;
                    let tempDisplayName = displayName;
                    while (true) {
                        if (displayNames.indexOf(displayName) < 0)
                            break;
                        i++;
                        displayName = tempDisplayName.concat(i);
                    }
                    displayNames.push(displayName);
                    oqls.push("[", displayName, "]", ' ', $this.getAttributSQLType(attribute));
                    if (attribute.oqlExpressions && attribute.oqlExpressions.length > 0) {
                        attribute.oqlExpressions.forEach((oqlExpression, index) => {
                            oqls.push(",", "\r\n", "  ");
                            let expressionDisplayName = displayName.concat("_",
                                this.removeSpecialChar(oqlParameter && oqlParameter.useEngcolumnAliasName ? oqlExpression.code : oqlExpression.name));
                            let tempExpressionDisplayName = expressionDisplayName;
                            let i = 0;
                            while (true) {
                                if (displayNames.indexOf(expressionDisplayName) < 0)
                                    break;
                                i++;
                                expressionDisplayName = tempExpressionDisplayName.concat(i);
                            }
                            displayNames.push(expressionDisplayName);
                            oqls.push("[", expressionDisplayName, "]", ' ', typeof oqlExpression.SQLType === "function" ?
                                oqlExpression.SQLType.call($this, attribute) : oqlExpression.SQLType);
                        });
                    }
                }
            });
            oqls.push("\r\n", ")");
            oqls.push("\r\n" + "INSERT INTO #" + metedata.Name + "TempTable");
            return oqls.join("");
        },
        //获取属性的SQL类型
        getAttributSQLType(attribute) {
            //基础类型
            if (attribute.DataTypeFlag === 0) {
                if (attribute.DataTypeKey.FullName === "System.String")
                    return "NVARCHAR(" + (attribute.Length > 0 ? attribute.Length : "MAX") + ")";
                if (attribute.DataTypeKey.FullName === "System.Int32")
                    return "INT";
                if (attribute.DataTypeKey.FullName === "System.Int64")
                    return "BIGINT";
                if ((attribute.DataTypeKey.FullName === "System.Date"
                    || attribute.DataTypeKey.FullName === "System.DateTime"))
                    return "DATETIME";
                if (attribute.DataTypeKey.FullName === "System.Decimal")
                    return "DECIMAL(" + attribute.Precision + ',' + attribute.Scale + ")";
                if (attribute.DataTypeKey.FullName === "System.Boolean")
                    return "BIT";
                if (attribute.DataTypeKey.FullName === "System.Guid")
                    return "NVARCHAR(50)";
                if (attribute.DataTypeKey.FullName === "System.Byte[]")
                    return "VARBINARY(MAX)";
            }
            //实体
            if (attribute.DataTypeFlag === 1) return "BIGINT";
            //枚举
            if (attribute.DataTypeFlag === 3) return "INT";
            return "";
        },
        //添加实体或集合属性进关联属性集合
        addAttributeInAssociationAttributes(associationAttributes, attribute) {
            let parentAttribute = attribute.parentAttribute;
            if (parentAttribute)
                this.addAttributeInAssociationAttributes(associationAttributes, parentAttribute);
            if (attribute.DataTypeFlag === 1 || attribute.DataTypeFlag === 4) {
                if (associationAttributes.indexOf(attribute) < 0)
                    associationAttributes.push(attribute);
            }
        },
        //创建属性的树节点
        createAttributeTreeElement(elements, element, attribute) {
            let isChild = false;
            for (let i = 0; i < element.childElements.length; i++) {
                if (attribute.fullExpression.startsWith(element.childElements[i].attribute.fullExpression)) {
                    this.createAttributeTreeElement(elements, element.childElements[i], attribute);
                    isChild = true;
                    break;
                }
            }
            if (!isChild) {
                let childElement = {
                    attribute: attribute,
                    tableAliasName: attribute.fullExpression.replace(/\./g, "_"),
                    childElements: []
                };
                elements.push(childElement);
                element.childElements.push(childElement);
            }
        },
        //添加关联表到Oql中
        addJoinTableInOql(oqls, treeElement, parentTableAliasName, isNullable) {
            if (isNullable === undefined)
                isNullable = treeElement.attribute.IsNullable;
            oqls.push("\r\n", "  ", isNullable || treeElement.attribute.IsNullable ? "left join " : "inner join ",
                this.getEntityOQLFullName(treeElement.attribute.DataTypeKey.FullName), " ", treeElement.tableAliasName);
            let association = treeElement.attribute.association;
            if (association) {
                if (association.Kind === 0) {
                    let fieldName = treeElement.attribute.Name;
                    let parentAttribute = treeElement.attribute.parentAttribute;
                    while (parentAttribute) {
                        if (parentAttribute.DataTypeFlag === 2) {
                            fieldName = parentAttribute.Name + "." + fieldName;
                            parentAttribute = parentAttribute.parentAttribute;
                        } else {
                            break;
                        }
                    }
                    oqls.push(" on ", treeElement.tableAliasName, ".ID", " = ", parentTableAliasName, ".", fieldName)
                } else {
                    oqls.push(" on ", treeElement.tableAliasName, ".", association.ChildMemberKey.Name, " = ", parentTableAliasName, ".ID")
                }
            }
            else {
                let fieldName = treeElement.attribute.Name;
                let parentAttribute = treeElement.attribute.parentAttribute;
                while (parentAttribute) {
                    if (parentAttribute.DataTypeFlag === 2) {
                        fieldName = parentAttribute.Name + "." + fieldName;
                        parentAttribute = parentAttribute.parentAttribute;
                    } else {
                        break;
                    }
                }
                oqls.push(" on ", treeElement.tableAliasName, ".ID", " = ", parentTableAliasName, ".", treeElement.attribute.Name);
            }
            if (treeElement.childElements && treeElement.childElements.length > 0) {
                treeElement.childElements.forEach((childElement, index) => {
                    this.addJoinTableInOql(oqls, childElement, treeElement.tableAliasName, isNullable || treeElement.attribute.IsNullable);
                });
            }
        },
        //获取属性的父级节点
        getAttributeParentTreeElement(allElements, attribute) {
            let parentAttribute = this.getAttributeEntityParentAttribute(attribute);
            if (!parentAttribute) return null;
            while (parentAttribute) {
                let parentElement = allElements.find((item) => item.attribute === parentAttribute);
                if (parentElement) return parentElement;
                parentAttribute = parentAttribute.parentAttribute;
            }
        },
        //找到属性的实体父属性
        getAttributeEntityParentAttribute(attribute) {
            if (!attribute.parentAttribute) return NaN;
            let parentAttribute = attribute.parentAttribute;
            if (parentAttribute.DataTypeFlag !== 2) return parentAttribute;
            while (true) {
                return this.getAttributeEntityParentAttribute(parentAttribute);
            }
        },
        //#endregion
        //#region 其它
        //类型格式化
        classTypeFormatter(row, column, cellValue, index) {
            return this.getEnumOptionName(this.enums.classTypeOptions, cellValue);
        },
        //获取项名称
        getEnumOptionName(options, optionValue) {
            let option = options.find((item) => item.value == optionValue);
            if (option) return option.name;
            return '';
        },
        //获取实体OQL全称
        getEntityOQLFullName(fullName) {
            if (!fullName) return '';
            return fullName.replace(/\./g, "::");
        },
        //联合数组
        joinArrayString(arr) {
            if (!arr) return '';
            return arr.join(",");
        },
        //清除特殊字符
        removeSpecialChar(str) {
            if (!str) return str;
            return str.replace(/[`~!#$%^\-&*)=|{}':;',.\\\[\]<>\/?～！＠＃￥％……＆×（）——＋｀－＝［］＼；＇，．／｛｝｜：“《》？\s]/g, "");
        },
        //字符串排序
        sortStringMethod(str1, str2) {
            let res = 0
            for (let i = 0; ; i++) {
                if (!str1[i] || !str2[i]) {
                    res = str1.length - str2.length
                    break
                }
                const char1 = str1[i]
                const char1Type = this.getChartType(char1)
                const char2 = str2[i]
                const char2Type = this.getChartType(char2)
                // 类型相同的逐个比较字符
                if (char1Type[0] === char2Type[0]) {
                    if (char1 === char2) {
                        continue
                    } else {
                        if (char1Type[0] === 'zh') {
                            res = char1.localeCompare(char2)
                        } else if (char1Type[0] === 'en') {
                            res = char1.charCodeAt(0) - char2.charCodeAt(0)
                        } else {
                            res = char1 - char2
                        }
                        break
                    }
                } else {
                    // 类型不同的，直接用返回的数字相减
                    res = char1Type[1] - char2Type[1]
                    break
                }
            }
            return res
        },
        getChartType(char) {
            // 数字可按照排序的要求进行自定义，我这边产品的要求是
            // 数字（0->9）->大写字母（A->Z）->小写字母（a->z）->中文拼音（a->z）
            if (/^[\u4e00-\u9fa5]$/.test(char)) {
                return ['zh', 300]
            }
            if (/^[a-zA-Z]$/.test(char)) {
                return ['en', 200]
            }
            if (/^[0-9]$/.test(char)) {
                return ['number', 100]
            }
            return ['others', 999]
        },
        //点击复制到剪贴板函数
        copyToClipboard(content) {
            if (window.clipboardData) {
                window.clipboardData.setData('text', content);
            } else {
                (function (content) {
                    document.oncopy = function (e) {
                        e.clipboardData.setData('text', content);
                        e.preventDefault();
                        document.oncopy = null;
                    }
                })(content);
                document.execCommand('Copy');
            }
            this.$message({
                message: '复制成功',
                type: 'success',
                duration: 1000
            });
        },
        //#endregion
    },
    watch: {
    },
    computed: {
        urlObj: function () {
            var url = window.location.href;
            if (url) {
                var _url = url.split("?")[1];
                if (!_url) {
                    return {};
                }
                var windowHref = _url.split("&");
                var obj = {};
                for (var i = 0; i < windowHref.length; i++) {
                    var arr = windowHref[i].split("=");
                    obj[arr[0]] = arr[1]
                }
                return obj;
            }
        }
    }
})